/*
* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* openUBMC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*         http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <gtest/gtest.h>
#include <test_utilities/test_base.h>

#include "drivers/pcie_gpu_card/innosilicon/awm_m11p/awm_m11p_memory.h"
#include <mc/engine.h>
#include <mc/common.h>

namespace drivers {
namespace pcie_gpu_card {
namespace innosilicon {
namespace awm_m11p_test {

class awm_m11p_test_service : public mc::engine::service {
public:
    awm_m11p_test_service(const std::string& name) : mc::engine::service(name) {}
};

// ========================= awm_m11p_memory测试 =========================
class AwmM11pMemoryTest : public mc::test::TestWithEngine {
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        m_test_service = std::make_unique<awm_m11p_test_service>("bmc.openubmc.test_awm_m11p_memory");
        m_test_service->init();
        m_test_service->start();
    }
    static void TearDownTestSuite() {
        m_test_service->stop();
        TestWithEngine::TearDownTestSuite();
    }
    void SetUp() override {}
    void TearDown() override {}
    static std::unique_ptr<awm_m11p_test_service> m_test_service;
};
std::unique_ptr<awm_m11p_test_service> AwmM11pMemoryTest::m_test_service;

// 基本 start/stop
TEST_F(AwmM11pMemoryTest, basic_start_stop) {
    dev::awm_m11p_memory mem;
    EXPECT_TRUE(mem.start());
    EXPECT_TRUE(mem.stop());
}
// 构造函数默认
TEST_F(AwmM11pMemoryTest, default_constructor) {
    dev::awm_m11p_memory mem;
    EXPECT_EQ(mem.m_memory.Utilization, 0);
}
// init 空配置
TEST_F(AwmM11pMemoryTest, init_empty_config) {
    dev::awm_m11p_memory mem;
    mem.set_service(m_test_service.get());
    mc::mutable_dict config;
    mc::dict connector;
    EXPECT_TRUE(mem.init(config, connector));
}
// init 含成员配置
TEST_F(AwmM11pMemoryTest, init_with_properties) {
    dev::awm_m11p_memory mem;
    mem.set_service(m_test_service.get());
    mc::mutable_dict config;
    config["bmc.dev.Memory"] = mc::dict{{"Manufacturer", "InnoSilicon"}, {"PartNumber", "M11P-8GB"}};
    mc::dict connector;
    EXPECT_TRUE(mem.init(config, connector));
}
// reset_default_properties 覆盖全部字段
TEST_F(AwmM11pMemoryTest, reset_default_properties_all) {
    dev::awm_m11p_memory mem;
    ASSERT_TRUE(mem.reset_default_properties());
    EXPECT_EQ(mem.m_memory.Manufacturer, std::string());
    EXPECT_EQ(mem.m_memory.PartNumber, std::string());
    EXPECT_EQ(mem.m_memory.Utilization, 0);
    EXPECT_EQ(mem.m_memory.DoubleBitErrorPageCount, 0);
    EXPECT_EQ(mem.m_memory.SingleBitErrorPageCount, 0);
}
// 多次 reset_default_properties
TEST_F(AwmM11pMemoryTest, multiple_reset_default_properties) {
    dev::awm_m11p_memory mem;
    for (int i = 0; i < 3; i++) {
        EXPECT_TRUE(mem.reset_default_properties());
    }
}
// 多实例
TEST_F(AwmM11pMemoryTest, multi_instance) {
    std::vector<std::unique_ptr<dev::awm_m11p_memory>> memories;
    for (int i = 0; i < 3; i++) {
        auto mem = std::make_unique<dev::awm_m11p_memory>();
        mem->set_service(m_test_service.get());
        mem->set_object_name(("memory_" + std::to_string(i)).c_str());
        EXPECT_TRUE(mem->start());
        memories.push_back(std::move(mem));
    }
}

} // namespace awm_m11p_test
} // namespace innosilicon
} // namespace pcie_gpu_card
} // namespace drivers
